package com.berchen.线程八锁;

/**
 * 题目：判断打印的是one还是two
 *
 * sleep方法不会释放锁。作用只是让线程暂停一会。sleep可以放在任何地方。
 * wait方法会释放锁，wait方法只能放在同步代码块或同步方法中。
 *
 * 1、两个普通【同步】方法，两个线程，标准打印：one two
 *      普通方法，锁：new Number(); 线程1拿到了锁，那么就只有等线程1执行完毕才能执行线程2.
 * 2、新增Thread.sleep();在getOne方法中，one two
 *      普通方法，锁：new Number();，线程1拿到了锁，线程2就拿不到，虽然在线程1中Thread.sleep，但是【sleep不会释放锁】。
 * 3、新增普通方法：getThree.打印：three one two
 *      普通非同步方法，其他两个普通同步方法，锁是new Number();，线程1拿到锁，睡眠，线程2只有等待，没有锁进不去方法。这时候就只有线程3执行。getThree方法是非同步，不需要锁就可以进去，所以three先执行。
 * 4、两个普通【同步】方法，两个number对象，two one
 *      普通方法1：锁:1=new Number(); 普通方法2：锁：2=new Number(); 线程1拿到1锁，睡眠。线程2的锁是2，所以线程2直接就拿着2锁进入方法执行。
 * 5、一个普通【同步】方法、一个静态【同步】getOne方法，一个number对象，two one ()
 *      普通方法，锁：new Number(); 静态同步方法：锁：Number.class。线程1拿到1锁，睡眠。线程2的锁是2，所以线程2直接就拿着2进去方法执行。
 * 6、两个静态【同步】方法，one two （静态方法，只与对象相关，所以两个静态和两个非静态，一个number相同）
 * 7、一个普通【同步】方法，一个静态【同步】getOne方法，两个number对象，two one （静态方法与类相关，非静态方法只与对象相关）
 * 8、两个静态【同步】方法，两个number对象，one two   （静态方法，与对象多少无关。）
 *
 * 线程八锁的关键点：
 * 1、非静态方法的锁是this。静态方法是本类.Class。
 * 2、在一个时刻内，一把锁只能由一个线程持有，无论几个方法。
 */

/**
 * 1）一个类【Number】中两个普通的【同步】方法
 *  创建一个Number对象，哪么就只有一把锁，两个线程用该对象去分别调用两个同步方法；
 *  线程1拿到锁后，线程2就必须得等到线程1释放锁后，即线程1调用的方法执行完后，线程2才能获取到锁；
 * 2）一个类【Number】中两个普通的【同步】方法，在方法getOne增加Thread.sleep(1)；
 *  创建一个Number对象，哪么就只有一把锁，两个线程用该对象去分别调用两个同步方法；
 *  线程1拿到锁后，线程2会阻塞，此时线程1指向了sleep方法，sleep不会释放锁，因此线程2还是要等待线程1调用的getOne方法指向完毕，线程2才能拿到锁；
 * 3）一个类【Number】中两个普通【同步】方法，一个非【同步】方法；
 *  创建一个Number对象，哪么就只有一把锁，三个线程分别用该对象调用该对象的三个方法；
 *  线程1拿到锁，线程2阻塞，线程3执行非【同步】方法不会阻塞；
 * 4）一个类【Number】中两个普通【同步】方法，
 *  创建两个Number对象，哪么就有2把锁，两个线程分别用着两个对象去调用者两个方法；
 *  线程1用锁1执行拿到锁，线程2用锁2执行拿到锁；两者互补干扰
 * 5）一个类【Number】中一个普通【同步方法】，一个静态【同步】方法
 *  创建一个Number对象，对象有一把锁，Number.class有一把锁；
 *  线程1用该对象调用普通【同步】方法拿到锁，线程2用该对象调用静态【同步】方法也能拿到锁，两者互不干扰；
 * 6）一个类【Number】中两个静态的【同步】方法
 *  创建一个Number对象，哪么就只有一把锁，两个线程用该对象去分别调用两个同步方法；
 *  静态方法，只与对象相关，所以两个静态【同步】方法用一个、多个对象和两个非静态【同步】用一个number对象调用相同
 * 7）一个类【Number】中一个普通【同步方法】，一个静态【同步】方法
 *  创建2个Number对象，对象有一把锁，Number.class有一把锁；
 *  线程1用对象1调用 普通【同步】方法拿到锁，线程2用对象2调用 静态【同步】方法也能拿到锁，两者互不干扰；
 * 8）一个类【Number】中两个静态的【同步】方法
 *  创建2个Number对象；
 *  静态方法，与对象多少无关
 */
public class TestThread8Monitor {

    public static void main(String[] args){

        Number num=new Number();
        Number num2=new Number();
        new Thread(new Runnable() {
            @Override
            public void run() {

                num.getOne();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {

//                num.getTwo();
                num2.getTwo();
            }
        }).start();
        /*new Thread(new Runnable() {
            @Override
            public void run() {

                num.getThree();
            }
        }).start();*/
    }
}
class Number{

    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("ONE");
    }
    public static synchronized void getTwo(){
        System.out.println("TWO");
    }
    /*public void getThree(){
        System.out.println("THREE");
    }*/
}
